package cn.edu.sgu.www.mhxysy.service.wenshi.impl;

import cn.edu.sgu.www.mhxysy.vo.Imager;
import cn.edu.sgu.www.mhxysy.pager.Pager;
import cn.edu.sgu.www.mhxysy.consts.CustomMessages;
import cn.edu.sgu.www.mhxysy.dto.wenshi.WenshiDTO;
import cn.edu.sgu.www.mhxysy.dto.wenshi.ZuoqiWenshiDTO;
import cn.edu.sgu.www.mhxysy.entity.wenshi.Wenshi;
import cn.edu.sgu.www.mhxysy.entity.wenshi.WenshiAttribute;
import cn.edu.sgu.www.mhxysy.entity.wenshi.WenshiCategory;
import cn.edu.sgu.www.mhxysy.entity.wenshi.WenshiViewAttribute;
import cn.edu.sgu.www.mhxysy.entity.zuoqi.ZuoqiSkill;
import cn.edu.sgu.www.mhxysy.entity.zuoqi.ZuoqiSkillCategory;
import cn.edu.sgu.www.mhxysy.entity.wenshi.ZuoqiWenshi;
import cn.edu.sgu.www.mhxysy.enums.InlayStatus;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.mapper.wenshi.WenshiAttributeMapper;
import cn.edu.sgu.www.mhxysy.mapper.wenshi.WenshiCategoryMapper;
import cn.edu.sgu.www.mhxysy.mapper.wenshi.WenshiMapper;
import cn.edu.sgu.www.mhxysy.mapper.wenshi.WenshiViewAttributeMapper;
import cn.edu.sgu.www.mhxysy.mapper.zuoqi.ZuoqiSkillCategoryMapper;
import cn.edu.sgu.www.mhxysy.mapper.zuoqi.ZuoqiSkillMapper;
import cn.edu.sgu.www.mhxysy.mapper.wenshi.ZuoqiWenshiMapper;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.service.wenshi.WenshiService;
import cn.edu.sgu.www.mhxysy.util.MathUtils;
import cn.edu.sgu.www.mhxysy.util.ObjectUtils;
import cn.edu.sgu.www.mhxysy.vo.wenshi.WenshiVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class WenshiServiceImpl implements WenshiService {

    private final WenshiMapper wenshiMapper;
    private final ZuoqiSkillMapper zuoqiSkillMapper;
    private final ZuoqiWenshiMapper zuoqiWenshiMapper;
    private final WenshiCategoryMapper wenshiCategoryMapper;
    private final WenshiAttributeMapper wenshiAttributeMapper;
    private final ZuoqiSkillCategoryMapper zuoqiSkillCategoryMapper;
    private final WenshiViewAttributeMapper wenshiViewAttributeMapper;

    @Autowired
    public WenshiServiceImpl(
            WenshiMapper wenshiMapper,
            ZuoqiSkillMapper zuoqiSkillMapper,
            ZuoqiWenshiMapper zuoqiWenshiMapper,
            WenshiCategoryMapper wenshiCategoryMapper,
            WenshiAttributeMapper wenshiAttributeMapper,
            ZuoqiSkillCategoryMapper zuoqiSkillCategoryMapper,
            WenshiViewAttributeMapper wenshiViewAttributeMapper) {
        this.wenshiMapper = wenshiMapper;
        this.zuoqiSkillMapper = zuoqiSkillMapper;
        this.zuoqiWenshiMapper = zuoqiWenshiMapper;
        this.wenshiCategoryMapper = wenshiCategoryMapper;
        this.wenshiAttributeMapper = wenshiAttributeMapper;
        this.zuoqiSkillCategoryMapper = zuoqiSkillCategoryMapper;
        this.wenshiViewAttributeMapper = wenshiViewAttributeMapper;
    }

    @Override
    public void clone(String wenshiId) {
        // 查询纹饰属性
        QueryWrapper<WenshiAttribute> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("wenshi_id", wenshiId);

        List<WenshiAttribute> list = wenshiAttributeMapper.selectList(queryWrapper);

        // 查询纹饰属性
        Wenshi wenshi = wenshiMapper.selectById(wenshiId);

        // 添加纹饰
        wenshi.setId(wenshi.uuid());

        wenshiMapper.insert(wenshi);

        // 批量添加纹饰属性
        for (int i = 0; i < list.size(); i++) {
            WenshiAttribute wenshiAttribute = list.get(i);

            wenshiAttribute.setId(wenshiAttribute.uuid() + (i + 1));
            wenshiAttribute.setWenshiId(wenshi.getId());

            wenshiAttributeMapper.insert(wenshiAttribute);
        }
    }

    @Override
    public void inlay(ZuoqiWenshiDTO zuoqiWenshiDTO) {
        String zuoqiId = zuoqiWenshiDTO.getZuoqiId();
        String wenshiId = zuoqiWenshiDTO.getWenshiId();
        Integer location = zuoqiWenshiDTO.getLocation();
        Integer inlayStatus = zuoqiWenshiDTO.getInlayStatus();

        // 和数据库中的纹饰状态对比
        Wenshi wenshi = wenshiMapper.selectById(wenshiId);

        if (!inlayStatus.equals(wenshi.getInlayStatus())) {
            throw new GlobalException(ResponseCode.CONFLICT, "纹饰的状态已经更新，请刷新页面后重新操作！");
        }

        // 纹饰状态为[0-未镶嵌]，则操作为【镶嵌】
        if (InlayStatus.WXQ.getValue().equals(inlayStatus)) {
            /*
             * 1、检查镶嵌纹饰的数量，每只坐骑最多可以镶嵌3颗纹饰
             */
            // 通过坐骑ID查询坐骑纹饰数量
            QueryWrapper<ZuoqiWenshi> queryWrapper = new QueryWrapper<>();

            queryWrapper.eq("zuoqi_id", zuoqiId);

            Long count = zuoqiWenshiMapper.selectCount(queryWrapper);

            // 已经镶嵌3颗纹饰，抛出异常
            if (count >= 3) {
                throw new GlobalException(ResponseCode.CONFLICT, "此坐骑镶嵌的纹饰数量已上限！");
            }

            // 同一位置不允许重复镶嵌纹饰
            queryWrapper.eq("location", location);

            Long selectCount = zuoqiWenshiMapper.selectCount(queryWrapper);

            if (selectCount > 0) {
                throw new GlobalException(ResponseCode.CONFLICT, "该位置已经镶嵌了纹饰！");
            }

            /*
             * 2、修改纹饰信息
             */
            UpdateWrapper<Wenshi> updateWrapper = new UpdateWrapper<>();

            updateWrapper.eq("id", wenshiId);
            updateWrapper.eq("inlay_status", InlayStatus.WXQ.getValue());

            updateWrapper.set("inlay_status", InlayStatus.YXQ.getValue());

            int update = wenshiMapper.update(updateWrapper.getEntity(), updateWrapper);

            if (update < 1) {
                throw new GlobalException(ResponseCode.SERVER_ERROR, "数据更新失败，请刷新页面后重试。");
            }

            // 添加坐骑-纹饰
            ZuoqiWenshi zuoqiWenshi = new ZuoqiWenshi();

            zuoqiWenshi.setId(null);
            zuoqiWenshi.setZuoqiId(zuoqiId);
            zuoqiWenshi.setWenshiId(wenshiId);
            zuoqiWenshi.setLocation(location);

            zuoqiWenshiMapper.insert(zuoqiWenshi);

            /*
             * 3、已经镶嵌两颗纹饰
             * 需要考虑不同的纹饰类型会激活不同的纹饰技能
             */
            if (count == 2) {
                // 创建一个map保存红色、黄色、蓝色纹饰的数量
                Map<Integer, Integer> countMap = new HashMap<>();

                countMap.put(1, 0);
                countMap.put(2, 0);
                countMap.put(3, 0);

                // 查询镶嵌在坐骑上的所有纹饰
                List<WenshiCategory> list = zuoqiWenshiMapper.selectByZuoqiId(zuoqiId);

                list.forEach(new Consumer<WenshiCategory>() {
                    @Override
                    public void accept(WenshiCategory wenshiCategory) {
                        Integer type = wenshiCategory.getType();
                        Integer count;

                        if ((count = countMap.get(type)) > 0) {
                            count ++;
                        } else {
                            count = 1;
                        }

                        countMap.put(type, count);
                    }
                });

                // 查询全部坐骑技能类型
                List<ZuoqiSkillCategory> categoryList = zuoqiSkillCategoryMapper.selectList(null);

                for (ZuoqiSkillCategory zuoqiSkillCategory : categoryList) {
                    Integer redCount = zuoqiSkillCategory.getRedCount();
                    Integer blueCount = zuoqiSkillCategory.getBlueCount();
                    Integer yellowCount = zuoqiSkillCategory.getYellowCount();

                    // 纹饰的搭配激活了坐骑技能
                    if (redCount.equals(countMap.get(1))
                            && blueCount.equals(countMap.get(3))
                            && yellowCount.equals(countMap.get(2))) {
                        // 查询已有的坐骑技能
                        Map<String, Object> columnMap = new HashMap<>();

                        columnMap.put("zuoqi_id", zuoqiId);

                        List<ZuoqiSkill> zuoqiSkills = zuoqiSkillMapper.selectByMap(columnMap);

                        // 添加对应的坐骑技能
                        ZuoqiSkill zuoqiSkill = new ZuoqiSkill();

                        zuoqiSkill.setZuoqiId(zuoqiId);
                        zuoqiSkill.setSkillId(zuoqiSkillCategory.getId());

                        switch (zuoqiSkills.size()) {
                            case 0: // 没有坐骑技能，添加一个
                                zuoqiSkill.setId(zuoqiSkill.uuid());

                                zuoqiSkillMapper.insert(zuoqiSkill);

                                break;
                            case 1: // 已经有一个坐骑技能，修改
                                zuoqiSkill.setId(zuoqiSkills.get(0).getId());

                                zuoqiSkillMapper.updateById(zuoqiSkill);

                                break;
                            default: // 发现多个坐骑技能，先删除，再添加
                                int delete = zuoqiSkillMapper.deleteByMap(columnMap);

                                if (delete > 1) {
                                    zuoqiSkill.setId(zuoqiSkill.uuid());

                                    zuoqiSkillMapper.insert(zuoqiSkill);
                                }

                                break;
                        }

                        break;
                    }
                }
            }
        } else if (InlayStatus.YXQ.getValue().equals(inlayStatus)) { // 纹饰状态为[1-镶嵌中]，则操作为【取下】
            // 通过坐骑ID查询坐骑技能数量
            QueryWrapper<ZuoqiSkill> queryWrapper = new QueryWrapper<>();

            queryWrapper.eq("zuoqi_id", zuoqiId);

            long total = zuoqiSkillMapper.selectCount(queryWrapper);

            // 如果坐骑技能不为空，通过坐骑ID删除坐骑技能
            if (total > 0) {
                zuoqiSkillMapper.delete(queryWrapper);
            }

            // 更新纹饰信息：镶嵌状态为0-未镶嵌
            UpdateWrapper<Wenshi> updateWrapper = new UpdateWrapper<>();

            updateWrapper.eq("id", wenshiId);
            updateWrapper.eq("inlay_status", InlayStatus.YXQ.getValue());

            updateWrapper.set("inlay_status", InlayStatus.WXQ.getValue());

            wenshiMapper.update(updateWrapper.getEntity(), updateWrapper);

            // 删除坐骑-纹饰
            Map<String, Object> columnMap = new HashMap<>();

            columnMap.put("zuoqi_id", zuoqiId);
            columnMap.put("location", location);

            zuoqiWenshiMapper.deleteByMap(columnMap);
        } else {
            throw new GlobalException(ResponseCode.BAD_REQUEST, "纹饰的状态值不合法：" + inlayStatus);
        }
    }

    @Override
    public void insert(WenshiDTO wenshiDTO) {
        /*
         * 1、添加纹饰
         */
        Wenshi wenshi = toEntity(wenshiDTO);
        String wenshiId = wenshi.uuid();

        wenshi.setId(wenshiId);
        wenshi.setInlayStatus(InlayStatus.WXQ.getValue());

        wenshiMapper.insert(wenshi);

        /*
         * 2、添加纹饰属性
         */
        // 查询纹饰类型
        WenshiCategory wenshiCategory = wenshiCategoryMapper.selectById(wenshiDTO.getCategoryId());

        // 通过纹饰类型查询纹饰属性类型
        QueryWrapper<WenshiViewAttribute> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("type", wenshiCategory.getType());

        List<WenshiViewAttribute> list = wenshiViewAttributeMapper.selectList(queryWrapper);

        /*
         * 1级纹饰有3条属性，2级纹饰有4条属性，3级纹饰有5条属性
         * 因此：纹饰属性条数 = 纹饰等级 + 2
         */
        // 为纹饰随机添加grade+2条属性
        for (int i = 0; i < wenshiCategory.getGrade() + 2; i++) {
            // 生成随机下标
            int random = MathUtils.random(0, list.size() - 1);

            // 添加纹饰属性
            WenshiAttribute wenshiAttribute = new WenshiAttribute();

            wenshiAttribute.setId(wenshiAttribute.uuid() + (i + 1));
            wenshiAttribute.setWenshiId(wenshiId);
            wenshiAttribute.setAttributeId(list.get(random).getId());

            wenshiAttributeMapper.insert(wenshiAttribute);
        }
    }

    @Override
    public void deleteById(String wenshiId) {
        // 1、删除坐骑-纹饰和坐骑-技能
        Wenshi wenshi = wenshiMapper.selectById(wenshiId);

        Integer inlayStatus = wenshi.getInlayStatus();

        if (InlayStatus.YXQ.getValue().equals(inlayStatus)) {
            QueryWrapper<ZuoqiWenshi> queryWrapper = new QueryWrapper<>();

            queryWrapper.eq("wenshi_id", wenshiId);

            List<ZuoqiWenshi> list = zuoqiWenshiMapper.selectList(queryWrapper);

            // 理论上这里的集合大小为0或1
            if (list.size() > 0) {
                // 删除坐骑-纹饰
                zuoqiWenshiMapper.delete(queryWrapper);

                // 删除坐骑-技能
                list.forEach(new Consumer<ZuoqiWenshi>() {
                    @Override
                    public void accept(ZuoqiWenshi zuoqiWenshi) {
                        // 通过坐骑ID查询坐骑技能
                        QueryWrapper<ZuoqiSkill> queryWrapper = new QueryWrapper<>();

                        queryWrapper.eq("zuoqi_id", zuoqiWenshi.getZuoqiId());

                        Long count = zuoqiSkillMapper.selectCount(queryWrapper);

                        // 坐骑技能不为空，删除
                        if (count > 0) {
                            zuoqiSkillMapper.delete(queryWrapper);
                        }
                    }
                });
            }
        }

        // 2、删除纹饰属性
        QueryWrapper<WenshiAttribute> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("wenshi_id", wenshiId);

        wenshiAttributeMapper.delete(queryWrapper);

        // 3、删除纹饰
        wenshiMapper.deleteById(wenshiId);
    }

    @Override
    public void updateById(WenshiDTO wenshiDTO) {
        String wenshiId = wenshiDTO.getId();

        /*
         * 修改前的数据检查
         */
        ObjectUtils.requireNonNull(wenshiId, CustomMessages.ID_NOT_NULL);

        Wenshi data = wenshiMapper.selectById(wenshiId);

        // 纹饰不存在，抛出异常
        if (data == null) {
            throw new GlobalException(ResponseCode.NOT_FOUND, "修改失败，纹饰不存在！");
        }

        Wenshi wenshi = toEntity(wenshiDTO);

        wenshiMapper.updateById(wenshi);
    }

    @Override
    public WenshiVO selectDetail(String wenshiId) {
        return wenshiMapper.selectDetail(wenshiId);
    }

    @Override
    public List<Imager> selectByZuoqiId(String zuoqiId) {
        return wenshiMapper.selectByZuoqiId(zuoqiId);
    }

    @Override
    public Page<Wenshi> selectByPage(Pager<Wenshi> pager) {
        QueryWrapper<Wenshi> queryWrapper = Pager.getQueryWrapper(pager, true);
        Page<Wenshi> page = Pager.ofPage(pager);

        return wenshiMapper.selectPage(page, queryWrapper);
    }

    @Override
    public List<WenshiVO> selectDetails(Integer categoryId) {
        return wenshiMapper.selectDetails(categoryId);
    }

    private Wenshi toEntity(WenshiDTO wenshiDTO) {
        Wenshi wenshi = new Wenshi();

        wenshi.setId(wenshiDTO.getId());
        wenshi.setRoleId(wenshiDTO.getRoleId());
        wenshi.setCategoryId(wenshiDTO.getCategoryId());
        wenshi.setDurability(wenshiDTO.getDurability());

        return wenshi;
    }

}